戻る

diffのexit statusは差分があれば1

テスティングフレームワークとか使わずに簡易的にプログラムをテストしたい場合、どんな言語でも最初はシェルスクリプトを使ったりする。標準出力を比較するだけでいい場合とかは結構手軽だ。

あるとき、複数行の出力を比較したくなったときに、実行結果と期待値を一旦ファイルとして書き出して、その2つのファイルをdiffで比較する、というのをテストのスクリプトに書いた。そしたらなぜかexit statusが1でファイルが途中で止まってしまう。set -eしているので途中の処理が1を返したら止まること自体はおかしくないのだが、色々いじってみたらdiffを実行している行で止まっているっぽかった。

diffがおかしいのかと思って、その行のコマンドだけ叩いてみると普通に実行できる。diffそのものもおかしくない。なぜだ、、、と思っていたら、diffの結果ファイル同士に違いがある場合はexit statusが1になっているのに気づいた。

ぐぐってみると以下のページが見つかった。

https://askubuntu.com/questions/698784/exit-code-of-diff

https://man7.org/linux/man-pages/man1/diff.1.html

つまり、diffの仕様としては以下のようになっている。

  • 差分がない場合、exit status は 0
  • 差分がある場合、exit status は 1
  • エラーの場合、exit status は 2

というわけで、スクリプト中のコマンドの終了ステータスが0以外のときは途中で止まるようにしている場合はdiffをスクリプトに混ぜると想定外の挙動になったりするかもしれない。set -e をしないようにするなり、diffを使う行を set +eset -e で囲むなりしたほうが良さそうだ。多分CIとかの途中の処理でdiffを使う場合も同じ問題が起こると思う。(ちなみに -e でフラグを立てるのに +e でフラグを下ろす感じになってるの、+と-が逆の意味を持つ記号というところから来ているのだろうが、直感に反する感じになっていてモヤモヤする)

なんでこんな仕様になってるんだろう。diffというのは2つのファイルに違いがないことを「正しい」とみなすようだ。。。原本と複製を比較する的な発想なんだろうか。

newnakashimaのBlog